package com.rfsp.common.shiro;

import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.Filter;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.session.mgt.ServletContainerSessionManager;
import org.apache.shiro.web.session.mgt.WebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class ShiroConfig {

    @Value("${server.servlet.session.timeout}")
    int timeOut;

	LinkedHashMap<String, String> anonPath = new LinkedHashMap<String, String>(){{
        put("/login/login",		"anon");
        put("/login/err",		"anon");
        put("/login/developing","anon");
        put("/login/actionResult","anon");
        put("/login/logout",	"anon");

        put("/interfaceclient/orgDirectory/queryOrgDirectory","anon");

        put("/",  		"anon");
        put("/index",  	"anon");
        put("/captcha", "anon");
        put("/common",  "anon");
        put("/main",  	"anon");
        put("/404",  	"anon");


        put("/hos/miList", "anon");
        put("/bank/businessRules1", "anon");
        put("/bank/businessRules2", "anon");

        put("/demo/**", "anon");

        put("/**",	    "anon");


	}};

    //2. 配置ShiroDialect，用于Shiro和thymeleaf标签配合使用
    //若不配置，可能导致前端使用shiro标签后无效果
    @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }

    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }

    //配置shiro session 的一个管理器, 默认使用容器的session管理
//    @Bean(name = "sessionManager")
//    public WebSessionManager sessionManager(){
//        return new ServletContainerSessionManager();
//    }

    // 配置会话管理器，使用自定义的SessionDAO
    @Bean("sessionManager")
    public SessionManager sessionManager(SpringSessionDAO sessionDAO) {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();

        sessionManager.setSessionDAO(sessionDAO);

        sessionManager.setGlobalSessionTimeout(timeOut * 1000L); // 30分钟超时
        sessionManager.setDeleteInvalidSessions(true);
        sessionManager.setSessionValidationSchedulerEnabled(true);

        return sessionManager;
    }

    //权限管理，配置主要是Realm的管理认证
    @Bean("securityManager")
    public DefaultWebSecurityManager securityManager(@Qualifier("shiroRealm")ShiroRealm shiroRealm, SessionManager sessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(shiroRealm);
        securityManager.setSessionManager(new ServletContainerSessionManager());
        return securityManager;
    }

//    @Bean("authc")
    public Filter getFilter(){
        return new URLPathFilter();
    }
    
//    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition(){
        DefaultShiroFilterChainDefinition chainDefinition=new DefaultShiroFilterChainDefinition();
        chainDefinition.addPathDefinitions(anonPath);
        return chainDefinition;
    }
    
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager")SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        Map<String, Filter> filterMap = new LinkedHashMap<>();
        // 若CustomShiroUserFilter交由spring管理的话会导致filter在shiroFilter之外而且运行在shiroFilter之前了，导致无法bind securityManager
        filterMap.put("authc", new URLPathFilter());
        shiroFilterFactoryBean.setFilters(filterMap);
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/login/login");
        shiroFilterFactoryBean.setSuccessUrl("/main");
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(anonPath);

        return shiroFilterFactoryBean;
    }


    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager")SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}
